mysql에서 그룹별 최신 데이터 가져오기

January 11, 2021

아래의 표와 같이 그룹을 user_id로 했을 때 user_id가 1인 경우 level 3, user_id가 2인 경우 level이 2라는 각 그룹의 최신 데이터를 조회하는 요구사항이 있을 수 있다.

id user_id level
1 1 1
2 1 2
3 1 3
4 2 1
5 2 2

.
.
.

mysql에서는 아래 쿼리와 같이 group by를 사용해서 각 그룹의 id 최대 값을 구하는 서브 쿼리를 조인하여 구할 수 있다.

select t1.id, t1.user_id, t1.level
from test_t as t1
         join (select max(id) as id from test_t group by user_id) as t2 on t1.id = t2.id;

다른 방법으로는 아래 쿼리와 같이 self join을 통해 같은 결과를 구할 수 있다.

select t1.id, t1.user_id, t1.level
from test_t as t1
         left join test_t as t2 on t1.user_id = t2.user_id and t1.id < t2.id
where t2.id is null;

필자는 user_id 100,000개와 각 user_id 마다 5개씩 총 500,000개 데이터로 테스트를 진행했다. 그리고 user_id에 index 설정을 하였다.

테스트 결과 user_id에 index를 설정 한 뒤 확인한 결과, 서브 쿼리를 사용한 첫 번째 쿼리보다 두 번째 쿼리가 성능이 더 뛰어난 것을 확인할 수 있었다.

또한 두 번째 쿼리는 from 절에 서브 쿼리를 사용할 수 없는 JPQL 기반인 querydsl에서도 사용할 수 있기 때문에 좀 더 유용하다.


Hello, world!